﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;

using Microsoft.WindowsMobile.Samples.Location; //GPS Reference
//using OpenNETCF.Net; //AP Reference
using OpenNETCF.Net.NetworkInformation;

//To-do list
//현재 파일크기를 표시 해주는 공간 만들기.
// 추후 10m 마다 Update 하도록 셋팅 예정 또는 속도에 따라 update 주기를 변경
// Wifi GPS Timer 와 Save Duration 조절 가능하도록 환경설정파일 저장 로드 부분 !
 

namespace Prototype_WPS_Net3._5
{

    public partial class WPS_Korea : Form
    {

        //AP
        bool foundWirelessNIC = false;
        private WirelessZeroConfigNetworkInterface m_wzc = null;
        private Timer m_wifiTimer = new Timer();
        private Timer m_GPSRdyTimer = new Timer();


        private readonly int SaveCond = 30;
        
        private readonly int GPS_timout_Cond = 300;
        //GPS
        private EventHandler updateHandler;
        private bool _HasValidData = false;
        private GpsDeviceState _LastDeviceState = null;  
        int MainState = 0;
        Gps gps;
        GpsPosition position;

        //
        GpsPosition prev_position;


        //HTTP Post
        private string SendString="";
        private string fileString="";


        //File IO Count when over 300 sec File Write
        private long SavetTme_cnt=0;

        // count GPS time out = 120;
        private long GPSTimeout_cnt = 0;
        private readonly string FILE_NAME = "WPS_LOG.txt";


        public WPS_Korea()
        {
            InitializeComponent();
            MainState = 0;

            //init GPS
            gps = new Gps();
            updateHandler = new EventHandler(speed);
            gps.LocationChanged += new LocationChangedEventHandler(LocationChanged);
            gps.DeviceStateChanged += new DeviceStateChangedEventHandler(DeviceStateChanged);

            // set up the WiFi timer
            m_wifiTimer.Interval = 2000; // 2sec
            m_wifiTimer.Tick += new EventHandler(m_wifiTimer_Tick);


            //GPS Ready Timer
            m_GPSRdyTimer.Interval = 1000; // 1sec
            m_GPSRdyTimer.Tick += new EventHandler(m_GPSRdyTimer_Tick);




            //Find Wireless Adapter
            FindWirelessAdapter();
            SavetTme_cnt = 0;


            //File size info 
            ShowFileInfo();
            //check if file don't exist and then create XML string
            if (!File.Exists(FILE_NAME))
                if(foundWirelessNIC==true)
                    Make_XML_header();

        }
        private void FindWirelessAdapter()
        {
            
            foreach (INetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
            {
                if (ni is WirelessNetworkInterface)
                {
                    // will be true for wireless or WZC
                    adapterName.Text = "Adapter : "+ ni.Name;
                    foundWirelessNIC = true;

                    if (ni is WirelessZeroConfigNetworkInterface)
                    {
                        m_wzc = ni as WirelessZeroConfigNetworkInterface;
                        //  refresh.Enabled = true;
                    }
                    else
                    {
                        apList.Items.Add("No WZC adapter found");
                        apList.Items.Add("Cannot retrieve nearby AP list");
                        apList.Enabled = false;
                    }

                    break;
                }
            }

            if (foundWirelessNIC)
            {
                ApListView();
            }
            else
            {
                MessageBox.Show("Could not find a compatible wireless network adapter");
            }

        }

        private void menuItem1_Click(object sender, EventArgs e)
        {

            if (MainState == 1)
            {

                MainState = 0;
                textBox2.Text = "Acquisition Stop" + "\r\n";
                menuItem1.Text = "Start";

                m_wifiTimer.Enabled = false;
                m_GPSRdyTimer.Enabled = false;

                if (gps.Opened)
                    gps.Close();
            }
            else
            {
                gps.Open();
                MainState = 1;
                if (_HasValidData == true)
                {
                    textBox2.Text = "Acquisition Start" + "\r\n";
                    m_wifiTimer.Enabled = true;
                }
                else
                {
                    textBox2.Text = "GPS Not Ready." + " Now Waiting. ";
                    m_GPSRdyTimer.Enabled = true;
                }
                
                menuItem1.Text = "Stop";



                

               // UpdateAPs();

            }
        }

        protected void LocationChanged(object sender, LocationChangedEventArgs args)
        {
            prev_position = args.Position;

            if (prev_position != null && prev_position.LatitudeValid == true
                && prev_position.LongitudeValid == true)
            {
                _HasValidData = true;
                
            }
            //Invoke(updateHandler);
        }
        protected void DeviceStateChanged(object sender, DeviceStateChangedEventArgs args)
        {
            _LastDeviceState = args.DeviceState;

            if (_LastDeviceState != null && _LastDeviceState.DeviceState == GpsServiceState.Off
                || _LastDeviceState.DeviceState == GpsServiceState.ShuttingDown
                || _LastDeviceState.DeviceState == GpsServiceState.Unknown
                || _LastDeviceState.DeviceState == GpsServiceState.Unloading)
            {
                _HasValidData = false;
            }

        }
        void speed(object sender, System.EventArgs args)
        {
          //  position = gps.GetPosition();

            /*

            if (position.LatitudeValid)
            {
                textBox1.Text += position.Latitude.ToString() + "\r\n";
            }
            if (position.LongitudeValid)
            {
                textBox1.Text += position.Longitude.ToString() + "\r\n";
            }
             
            if (position.SpeedValid)
            {
                textBox1.Text += "Speed :"+ position.Speed.ToString("0.00") + " Km/h";
            }

            if (position.HorizontalDilutionOfPrecisionValid)
            {
                textBox1.Text += "HDOP :" + position.HorizontalDilutionOfPrecision.ToString() ;
            }

            if (position.TimeValid)
            {
                textBox1.Text += position.Time.ToString() + " time" + "\r\n";

            }
             */
            /*
                        if (position.SeaLevelAltitudeValid)
                        {
                            textBox1.Text += position.SeaLevelAltitude.ToString() + " Ft" + "\r\n";
                        }
            */

        }

        /*
        //Update AP
        void UpdateAPs()
        {


            if (m_nearbyAPs == null)
            {
                m_nearbyAPs = m_currentAdapter.NearbyAccessPoints;
            }
            else
            {
                m_nearbyAPs.Refresh();
            }



            string[] cols = new string[4];
            textBox2.Text = "";
            foreach (AccessPoint ap in m_nearbyAPs)
            {

                BitConverter.ToString(m_currentAdapter.MacAddress); // current adapter MacAddress
                cols[0] = BitConverter.ToString(ap.MacAddress);  //ap.name
                cols[1] = ap.SignalStrength.Decibels.ToString();
                cols[2] = ap.SignalStrength.ToString();
                cols[3] = ap.InfrastructureMode.ToString(); // bss or ibss


                textBox2.Text += cols[0] + ": " + cols[1] + ": " + cols[2] + "\r\n";

            }


        }
        */

        void m_GPSRdyTimer_Tick(object sender, EventArgs e)
        {
            GPSTimeout_cnt++;
            if (_HasValidData == true)
            {
                GPSTimeout_cnt = 0;
                textBox2.Text = "Acquisition Start" + "\r\n";
                m_wifiTimer.Enabled = true;
                m_GPSRdyTimer.Enabled = false;
            }
            else
            {
                textBox2.Text = "GPS Not Ready" + " Now Waiting." + GPSTimeout_cnt;

                if (GPSTimeout_cnt > GPS_timout_Cond)
                {
                    GPSTimeout_cnt = 0;
                    m_GPSRdyTimer.Enabled = false;
                    menuItem1_Click(null,null);
                }

            }


        }


        void m_wifiTimer_Tick(object sender, EventArgs e)
        {
            // if we're on the config tab, stop looking for networks

            //UpdateAPs();
            if(_HasValidData==true)
                Make_XML_content();
            SavetTme_cnt++;

            if (SavetTme_cnt > SaveCond)
            {
                Write_XML();

                ShowFileInfo();
                
                SavetTme_cnt = 0;
            }



        }

        void Make_XML_header()
        {
            SendString = "<?xml version=\"1.0\"?>" + "<document>" + "\n";
            SendString += "<submitId>xlos</submitId>" + "\n";
            SendString += "<submitDeviceMac>";
            SendString += m_wzc.GetPhysicalAddress().ToString() + "\n";//BitConverter.ToString(m_currentAdapter.MacAddress) ;
            SendString += "</submitDeviceMac>" + "\n";
        }
        void Make_XML_content() //input variable name
        {
            
            //Write Uploader Information 

            SendString += "<item>" + "\n";

            //GET GPS
            textBox1.Text = "";
            position = gps.GetPosition();
            if (position.LatitudeValid)
            {
              //  textBox1.Text += position.Latitude.ToString() + "\r\n";
                SendString += "<latitude>" + position.Latitude.ToString() + "</latitude>" + "\n"; 
            }
            if (position.LongitudeValid)
            {
               // textBox1.Text += position.Longitude.ToString() + "\r\n";
                SendString += "<longitude>" + position.Longitude.ToString() + "</longitude>" + "\n"; 
            }
            if (position.SpeedValid)
            {
               // textBox1.Text += position.Speed.ToString() + " Km/h" + "\r\n";
                textBox1.Text += position.Speed.ToString("0.00") + " Km/h";
                SendString += "<velocity>" + position.Speed.ToString() + "</velocity>" + "\n"; 
            }

            if (position.HorizontalDilutionOfPrecisionValid)
            {
               // textBox1.Text += position.HorizontalDilutionOfPrecision.ToString() + " Km/h" + "\r\n";
                textBox1.Text += "  HDOP :" + position.HorizontalDilutionOfPrecision.ToString();
                SendString += "<hdop>" + position.HorizontalDilutionOfPrecision.ToString() + "</hdop>" + "\n"; 
            }

            if (position.TimeValid)
            {
                textBox1.Text += " "+ position.Time.ToString("yyyy-MM-dd hh:mm");

                SendString += "<detectTime>" + GetUnixTime(position.Time) + "</detectTime>" + "\n"; 

            }
            //GET AP
            //UI
            apList.Items.Clear();
            foreach (AccessPoint ap in m_wzc.NearbyAccessPoints)
            {
                char infra;
                
                //UI
                apList.Items.Add(string.Format("{0,-20} ({1,-5}) {2,-5} ", ap.PhysicalAddress.ToString(), ap.SignalStrength.Decibels+"dB", ap.Privacy == 0 ? "[open]" : "[WEP]"));

                SendString += "<ap>" + "\n";
                //BSSID  mac address
                SendString += "<bssid>" + ap.PhysicalAddress.ToString() + "</bssid>" + "\n"; 
                //SSID   AP name
                SendString += "<ssid>" + ap.Name + "</ssid>" + "\n"; 
        
                //Signal
                SendString += "<signal>" + ap.SignalStrength.Decibels + "</signal>" + "\n"; 
               // ap.SignalStrengthInDecibels;
               // ap.SignalStrength.Decibels.ToString();
               // ap.SignalStrength.ToString(); // NotAWirelessAdapter = 0, NoSignal = 1, VeryLow = 2, Low = 3, Good = 4, VeryGood = 5, Excellent = 6,

                //type




                infra = (char)ap.InfrastructureMode;
                if (infra == 0) //        AdHoc = 0,Infrastructure = 1,AutoUnknown = 2,
                {
                    SendString += "<type>" + "IBSS" + "</type>" + "\n";
                }
                else if (infra == 1)
                {
                    SendString += "<type>" + "BSS" + "</type>" + "\n";
                }
                else
                {
                    SendString += "<type>" + "Unkonwn" + "</type>" + "\n";
                }

                //Encryption
                SendString += "<encryption>" + (ap.Privacy == 0 ? "0" : "1") + "</encryption>" + "\n";
        

                //Channel
                SendString += "<channel>" + ap.Channel + "</channel>" + "\n";

                // speed rate // pending.
                SendString += "<speed>" + (ap.SupportedRates.Max()/1000) + "</speed>";

                SendString += "</ap>" + "\n";


            }

            SendString += "</item>" + "\n";
         //   SendString += "</document>" + "\n";



        }
        private void Write_XML()
        {
            //http://msdn.microsoft.com/ko-kr/library/6ka1wd3w.aspx
            //http://msdn.microsoft.com/ko-kr/library/3zc0w663.aspx
//          after writing, clear string variable

            

            if (File.Exists(FILE_NAME))
            {
                using (StreamWriter sw = File.AppendText(FILE_NAME))
                {
                    sw.WriteLine(SendString);
                    sw.Close();
                }

            }
            else
            {
                using (StreamWriter sw = File.CreateText(FILE_NAME))
                {

                    //sw.WriteLine("This is my file.");
                    sw.WriteLine(SendString);
              
                    sw.Close();
                }
            }

            SendString = "";

        }

        private int Read_XML()
        {
            int ret;
            
            try 
            {
                StreamReader textFile = new StreamReader(FILE_NAME);
                fileString = textFile.ReadToEnd();
                textFile.Close();
                /*
                // Create an instance of StreamReader to read from a file.
                // The using statement also closes the StreamReader.
                using (StreamReader sr = new StreamReader(FILE_NAME)) 
                {
                    // Read and display lines from the file until the end of 
                    // the file is reached.
                    while ((tmp = sr.ReadLine()) != null) 
                    {
                        fileString += tmp;
                    }
                }
                */
                
                ret = 1;
            }
            catch (Exception e) 
            {
                // Let the user know what went wrong.
                MessageBox.Show("The file could not be read: "+e.Message);
                ret = -1;
                
            }
            return ret;
        }



        private void ApListView()
        {
            if (m_wzc == null) return;

            apList.Items.Clear();

            foreach (AccessPoint ap in m_wzc.NearbyAccessPoints)
            {
                apList.Items.Add(string.Format("{0,-20} ({1,-5}) {2,-5} ", ap.PhysicalAddress.ToString(), ap.SignalStrength.Decibels + "dB", ap.Privacy == 0 ? "[open]" : "[WEP]"));
            }
        }
        public static string UploadFileEx(string uploadfile, string url,
            string fileFormName, string contenttype)
        {
            if ((fileFormName == null) ||
                (fileFormName.Length == 0))
            {
                fileFormName = "file";
            }

            if ((contenttype == null) ||
                (contenttype.Length == 0))
            {
                contenttype = "application/octet-stream";
            }


            //            string postdata;
            Uri uri = new Uri(url);


            string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
            HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(uri);

            webrequest.ContentType = "application/x-www-form-urlencoded; boundary=" + boundary;
            webrequest.Method = "POST";


            // Build up the post message header
            StringBuilder sb = new StringBuilder();
            sb.Append("--");
            sb.Append(boundary);
            sb.Append("\r\n");
            sb.Append("Content-Disposition: form-data; name=\"");
            sb.Append(fileFormName);
            sb.Append("\"; filename=\"");
            sb.Append(Path.GetFileName(uploadfile));
            sb.Append("\"");
            sb.Append("\r\n");
            sb.Append("Content-Type: ");
            sb.Append(contenttype);
            sb.Append("\r\n");
            sb.Append("\r\n");

            string postHeader = sb.ToString();
            byte[] postHeaderBytes = Encoding.UTF8.GetBytes(postHeader);

            // Build the trailing boundary string as a byte array
            // ensuring the boundary appears on a line by itself
            byte[] boundaryBytes =
                   Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

            FileStream fileStream = new FileStream(uploadfile,
                                        FileMode.Open, FileAccess.Read);
            long length = postHeaderBytes.Length + fileStream.Length +
                                                   boundaryBytes.Length;
            webrequest.ContentLength = length;
            webrequest.Timeout = 5000;
            webrequest.ReadWriteTimeout = 5000;

            try
            {
                Stream requestStream = webrequest.GetRequestStream();

                // Write out our post header
                requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);

                // Write out the file contents
                byte[] buffer = new Byte[checked((uint)Math.Min(4096,
                                         (int)fileStream.Length))];
                int bytesRead = 0;
                while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                    requestStream.Write(buffer, 0, bytesRead);

                // Write out the trailing boundary
                requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
                requestStream.Close();
                fileStream.Close();

                WebResponse responce = webrequest.GetResponse();
                Stream s = responce.GetResponseStream();
                StreamReader sr = new StreamReader(s);


                //get response ( web page )
                string resp = sr.ReadToEnd();

                responce.Close();
                s.Close();
                sr.Close();

                return resp;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);


                return "error";
                //throw ex;
            }





        }
        public static string http_POST(string XML, string url)
        {


             StringBuilder postParams = new StringBuilder();
             postParams.Append("xml=" + XML);
 

            Encoding encoding = Encoding.UTF8;
            byte[] result = encoding.GetBytes(postParams.ToString());

            // 타겟이 되는 웹페이지 URL
            string Url = url;  //수정해주세요.

            HttpWebRequest wReqFirst = (HttpWebRequest)WebRequest.Create(Url);

             // HttpWebRequest 오브젝트 설정
            wReqFirst.Method = "POST";
            wReqFirst.ContentType = "application/x-www-form-urlencoded";
            wReqFirst.ContentLength = result.Length;

            Stream postDataStream = wReqFirst.GetRequestStream();
            postDataStream.Write(result, 0, result.Length);
            postDataStream.Close();

            HttpWebResponse wRespFirst = (HttpWebResponse)wReqFirst.GetResponse();

            // Response의 결과를 스트림을 생성합니다.
            Stream respPostStream = wRespFirst.GetResponseStream();
            StreamReader readerPost = new StreamReader(respPostStream, Encoding.Default);

            // 생성한 스트림으로부터 string으로 변환합니다.
            string resultPost = readerPost.ReadToEnd();

            return resultPost;




        }
        private void menuItem2_Click(object sender, EventArgs e)
        {
            string flag_success;
            
            if (MainState == 1) //진행 중일때
            {
                menuItem1_Click(null, null); // 꺼버리고 시작
            }
            //m_wifiTimer.Enabled = false;

            // search if file exist
            if (File.Exists(FILE_NAME))
            {
                Read_XML();

                fileString += "</document>" + "\n";//add footer
                

                //HTTP POST Send
                flag_success = http_POST(fileString, "http://chaehyun.kr/openwps/submit/");


                if (flag_success.StartsWith("HTTP POST ERROR")) //fail
                {
                    textBox2.Text = "Sending failed, try again.";
                }
                else //success
                {
                    // txt file delete
                    File.Delete(FILE_NAME);
                    textBox2.Text = "Sending complete";
                }
                
            }
            //if not , message show. nofile
            else
            {
                textBox2.Text = "There's No Save file. push Start";
            }

            ShowFileInfo();
            





            //m_wifiTimer.Enabled = true;

        }

        private void ShowFileInfo()
        {
            //show File Info
            long filesize;
            filesize=GetFileSize();
            if(filesize>0)
            {
                FileInfo.Text = "File Size " + filesize/1024 + " KB";
            }
            else
            {
                FileInfo.Text = "NO File";
            }
        }
        private long GetFileSize()
        {
            long ret=0;

            if (File.Exists(FILE_NAME))
            {
                FileInfo f = new FileInfo(FILE_NAME);
                ret = f.Length;
            }
            else
            {
                ret = -1;
            }
            return ret;

            //http://dotnetperls.com/file-size
        }

        public static long GetUnixTime(DateTime dateTimeUtc)
        {
            TimeSpan timestamp;

            // Get seconds since Jannuary 1, 1970 GMT
            timestamp = dateTimeUtc - new DateTime(1970, 1, 1);

            return (long)Math.Floor(timestamp.TotalSeconds);
        }


    }









}


//comment
//WEB POST Reference http://www.onlybalance.pe.kr/xe/?mid=tech&category=99&document_srl=378

//File IO
//http://msdn.microsoft.com/ko-kr/library/system.io.file.aspx
